package com.achievo.reportserver.servlet;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.Session;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.broker.BrokerService;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
import org.apache.commons.jci.monitor.FilesystemAlterationListener;
import org.apache.commons.jci.monitor.FilesystemAlterationMonitor;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;

import com.achievo.reportserver.config.ConfigFactory;
import com.achievo.reportserver.config.DatasourceConfigListener;
import com.achievo.reportserver.config.ReportConfigFileListener;
import com.achievo.reportserver.converter.DateConverter;
import com.achievo.reportserver.ds.DataSourceFactory;
import com.achievo.reportserver.mq.EmaiMessageListener;
import com.achievo.reportserver.mq.JmsConfig;
import com.achievo.reportserver.mq.ReportConfigParserListener;

/**
 * 
 * Report Server
 * write at Jan 21, 2010
 * @author <a href="mailto:chinaoryx@gmail.com">Hyman.Zhang (Zhang Haipeng)</a>
 * @version 1.0
 * 
 *
 */
public class InitServlet extends HttpServlet {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(InitServlet.class);

	private static final long serialVersionUID = 1L;
	
	private ClassLoader classLoader = this.getClass().getClassLoader();
	
	

    /**
     * Default constructor. 
     * @throws MalformedURLException 
     */
    public InitServlet(){
    	
//    	URL url = classLoader.getResource("log4j.properties");
//    	PropertyConfigurator.configure(url);
    }

	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		if (logger.isDebugEnabled()) {
			logger.debug("doGet(HttpServletRequest=" + req + ", HttpServletResponse=" + resp + ") - start");
		}
//		ConfigFactory.getDatasourceConfig().getString("aaa");
		DataSource ds = DataSourceFactory.getDataSource("A");
		try {
			java.sql.Connection conn = ds.getConnection();
			logger.info("---------------------------------ds:" + conn);
			conn.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		super.doGet(req, resp);

		if (logger.isDebugEnabled()) {
			logger.debug("doGet(HttpServletRequest=" + req + ", HttpServletResponse=" + resp + ") - end");
		}
	}

	/**
	 * @see Servlet#init(ServletConfig)
	 */
	public void init(ServletConfig config) throws ServletException {
		if (logger.isDebugEnabled()) {
			logger.debug("init(ServletConfig) - start"); 
		}
		
		logger.info("starting mq broker!");
		try {
			startBroker();
		} catch (Exception e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		logger.info("started mq broker!");
		
		
		String filepath = config.getServletContext().getRealPath("");
		if (!filepath.endsWith(File.separator)) {
			filepath = filepath + File.separator;
		}
		ConfigFactory.SERVER_REAL_PATH = filepath;
		
		logger.info("register the Converter!");
		ConvertUtils.register(new DateConverter(), java.util.Date.class);
		
		
		logger.info("register the Converter!");
		String dynaReloadInterval = config.getInitParameter("dynamic-reload-inteval");
		String reportConfigRootFileName = config.getInitParameter("report-config-root-file");	
		int reloadInterval = 5000;		
		if (StringUtils.isEmpty(dynaReloadInterval) 
        		&& StringUtils.isNumeric(dynaReloadInterval))
        {
        	reloadInterval = Integer.parseInt(dynaReloadInterval) * 1000;
        }
		ConfigFactory.setReloadInterval(reloadInterval);
		
		
		logger.info("starting connection mq broker!");
		initJmsClient();
		logger.info("started connection mq broker!");
		
		
		logger.info("starting read the server config!");
		XMLConfiguration serverConfig = readServerConfig(reloadInterval);	
		logger.info("started read the server config!");
		
		logger.info("starting read the datasource config!");
		readDatasourceConfig(reloadInterval);
		logger.info("started read the datasource config!");
		
		
		logger.info("starting read the report config!");
		String reportConfigRoot = serverConfig.getString("reportConfigRoot");
		String reportTemplateRoot = serverConfig.getString("reportTemplateRoot");
		readReportConfigs(reportConfigRoot, reportTemplateRoot);
		logger.info("started read the report config!");
		
		
		logger.info("starting the email listner!");		
		Connection conn = JmsConfig.getEmailConsumerConn();
		// create javax.jms.Session
    	try {
			Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
			Queue queue = session.createQueue(JmsConfig.QUEUE_EMAIL);
			MessageConsumer consumer = session.createConsumer(queue);
	    	MessageListener listner = new EmaiMessageListener();
	    	consumer.setMessageListener(listner);  
		} catch (JMSException e) {
			logger.error("onFileCreate", e);
		}
		logger.info("started the email listner!");
		


		if (logger.isDebugEnabled()) {
			logger.debug("init(ServletConfig) - end"); 
		}
	}

	private void readReportConfigs(String reportConfigRoot, String reportTemplateRoot) {
		// add the report def root		
		FilesystemAlterationMonitor fam = new FilesystemAlterationMonitor();
		File file = new File(classLoader.getResource(reportConfigRoot).getFile());
		FilesystemAlterationListener listener = null;
		listener = new ReportConfigFileListener();
		fam.addListener(file, listener);
		
		File jasperDir = new File(classLoader.getResource(reportTemplateRoot).getFile());
		fam.addListener(jasperDir, listener);
		
		fam.start();
		
		
		
		
		
		
		
		Connection conn = JmsConfig.getConfigConsumerConn();
		// create javax.jms.Session
    	try {
			Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
			Queue queue = session.createQueue(JmsConfig.QUEUE_CONFIG);
			MessageConsumer consumer = session.createConsumer(queue);
	    	MessageListener listner = new ReportConfigParserListener();
	    	consumer.setMessageListener(listner);  
		} catch (JMSException e) {
			logger.error("onFileCreate", e);
		}
	}

	private void readDatasourceConfig(int reloadInterval) {
		// read the datasource config		
		PropertiesConfiguration datasourceConfig = null;
		try {
			datasourceConfig  = new PropertiesConfiguration(classLoader.getResource("datasource.properties"));
		} catch (ConfigurationException e1) {
			// TODO Auto-generated catch block
			logger.error("read datasource.properties fail!", e1);
		}
		if (reloadInterval > 0) {
			FileChangedReloadingStrategy fcrs = null;
			fcrs = new FileChangedReloadingStrategy();
			fcrs.setRefreshDelay(reloadInterval);	
			datasourceConfig.setReloadingStrategy(fcrs);
			logger.info("datasourceConfig set fcrs");
		} 
		datasourceConfig.addConfigurationListener(new DatasourceConfigListener());
		
		ConfigFactory.setDatasourceConfig(datasourceConfig);
		DataSourceFactory.refresh();
	}

	private XMLConfiguration readServerConfig(int reloadInterval) {
		// for report config, that had more than one config files.		
		XMLConfiguration serverConfig = null;
		try {
			serverConfig  = new XMLConfiguration(classLoader.getResource("server.xml"));
		} catch (ConfigurationException e1) {
			// TODO Auto-generated catch block
			logger.error("read server.xml fail!", e1);
		}
		if (reloadInterval > 0) {
			FileChangedReloadingStrategy fcrs = null;
			fcrs = new FileChangedReloadingStrategy();
			fcrs.setRefreshDelay(reloadInterval);	
			serverConfig.setReloadingStrategy(fcrs);
			logger.info("serverConfig set fcrs");
		} 
		ConfigFactory.setServerConfig(serverConfig);
		return serverConfig;
	}

	private void initJmsClient() {
		// init the JMS Client
		String url = "vm://fred:61616";
    	//create javax.jms.ConnectionFactory
    	ConnectionFactory connectionFactory = new ActiveMQConnectionFactory(null, null, url);  
    	// create javax.jms.Connection
    	Connection connection = null;
		try {
			connection = connectionFactory.createConnection();
			connection.start();
			JmsConfig.setConfigConsumerConn(connection);
			
			connection = connectionFactory.createConnection();
			connection.start();
			JmsConfig.setConfigProducerConn(connection);
			
			
			connection = connectionFactory.createConnection();
			connection.start();
			JmsConfig.setEmailConsumerConn(connection);
			
			
			connection = connectionFactory.createConnection();
			connection.start();
			JmsConfig.setEmailProducerConn(connection);
			
			
		} catch (JMSException e) {
			// TODO Auto-generated catch block			
			logger.error("start activeMq fail!", e);
		}
	}

	/**
	 * @see Servlet#destroy()
	 */
	public void destroy() {
		try {
			JmsConfig.getConfigConsumerConn().close();
			JmsConfig.getConfigProducerConn().close();
			JmsConfig.getEmailConsumerConn().close();
			JmsConfig.getEmailProducerConn().close();
		} catch (JMSException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
	
	private void startBroker() throws Exception
    {
    	BrokerService broker = new BrokerService();
    	// configure the broker
    	broker.setBrokerName("fred");
    	broker.addConnector("tcp://localhost:61616");
    	
    	// configure the jaas Plugin for security.
//    	JaasAuthenticationPlugin jaasPlugin = new JaasAuthenticationPlugin();
//    	jaasPlugin.setConfiguration("activemq-domain");
//    	broker.setPlugins(new BrokerPlugin[]{jaasPlugin});
    	
    	// start the broker
    	broker.start();
    }

}
